import {RecordType} from "./record";

export const BlockState = {
    notExists: 'not exists',  // 还未被申请出来
    inUse: 'in use',  // 已经被申请出来，还没被回收
    localRecycled: 'local recycled',  // 本地回收，但是因为多流原因，没有真正被回收
    recycled: 'recycled',  // 被回收，进入可用状态
    birthRecycled: 'free to birth',  // 通过流转被回收到birth stream pool
}
export function Block(blockId) {
    this.blockId = blockId;
    this.address = undefined;
    this.size = undefined;

    this.kernelType = undefined;
    this.kernelId = undefined;
    this.computeNodeName = undefined;

    this.birthStream = undefined;
    this.birthTime = undefined;
    this.birthRecycleTime = undefined;
    this.duration = undefined;

    this.streamsToInUseInTime = new Map(); // { timestamp: xx, type: alloc/wander }

    // 本地回收代表这条流上已经不再使用这块内存
    this.streamsToLocalRecycledTime = new Map();  // { time: xx }

    // 一块内存并不会在所有流上释放（也就是变成可用），在不同的流上，释放的时间可能也不一样
    this.streamsToBorrowRecycledTime = new Map();  // { timestamp: xx, type: free/migration }

    this.records = [];
}

function parseName(nameStr, block) {
    let es = nameStr.split('_');
    block.kernelType = es[0];
    block.kernelId = es[1];
    block.computeNodeName = es.slice(1, -1).join('_');
}

Block.prototype.addRecord = function(record) {
    this.records[this.records.length] = record;

    if (record.type === RecordType.allocMem) {
        this.address = record.address;
        this.size = parseInt(record.size);
        this.birthStream = record.stream;
        this.birthTime = record.timestamp;
        parseName(record.name, this);
    }

    if (record.type === RecordType.allocMem || record.type === RecordType.wander) {
        this.streamsToInUseInTime.set(record.stream, {
            timestamp: record.timestamp,
            type: record.type
        });
    } else if (record.type === RecordType.localRecycle) {
        this.streamsToLocalRecycledTime.set(record.stream, {
            timestamp: record.timestamp
        });
    } else if (record.type === RecordType.recycle) {
        this.streamsToBorrowRecycledTime.set(record.stream, {
            timestamp: record.timestamp,
            type: record.type
        });
    } else if (record.type === RecordType.birthRecycle) {
        this.birthRecycleTime = record.timestamp;
        this.duration = this.birthRecycleTime - this.birthTime;
    }
}

/**
 * 获取当前时间戳下，该Block在指定流的状态
 * @param timestamp
 * @param stream
 */
Block.prototype.getState = function(timestamp, stream) {
    let state = BlockState.notExists;

    if (this.streamsToInUseInTime.has(stream)) {
        if (timestamp < this.streamsToInUseInTime.get(stream).timestamp) {
            return state;
        }
        state = BlockState.inUse;
    }

    if (this.streamsToLocalRecycledTime.has(stream)) {
        if (timestamp < this.streamsToLocalRecycledTime.get(stream).timestamp) {
            return state;
        }
        state = BlockState.localRecycled;
    }

    if (this.streamsToBorrowRecycledTime.has(stream)) {
        if (timestamp < this.streamsToBorrowRecycledTime.get(stream).timestamp) {
            return state;
        }
        state = BlockState.recycled;
    }

    return state;
}
